/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.buffer;

import io.netty.util.ByteProcessor;
import io.netty.util.ReferenceCounted;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;

/**
 * 零个或多个字节(八位字节)的序列, 允许随机和顺序访问.
 * 该接口为一个或多个 primitive byte arrays ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers} 提供了抽象视图.
 *
 * <h3>创建一个 buffer</h3>
 * <p>
 * 推荐使用 {@link Unpooled} 中的帮助方法来创建新 buffer, 而不是直接调用单个实现的构造函数.
 *
 * <h3>随机存取索引</h3>
 * <p>
 * 就像普通的 primitive byte array, {@link ByteBuf} 使用 <a href="http://en.wikipedia.org/wiki/Zero-based_numbering">基于 0 的索引</a>.
 * 这意味着, 首个字节的索引总是 {@code 0}, 末尾字节的索引总是 {@link #capacity() capacity - 1}.
 * 例如, 要遍历 buffer 中的所有字节, 无论其内部实现如何, 都可以执行以下操作:
 *
 * <pre>
 * {@link ByteBuf} buffer = ...;
 * for (int i = 0; i &lt; buffer.capacity(); i ++) {
 *     byte b = buffer.getByte(i);
 *     System.out.println((char) b);
 * }
 * </pre>
 *
 * <h3>顺序访问索引</h3>
 * <p>
 * {@link ByteBuf} 提供两个指针变量来支持顺序读和写操作:
 * - {@link #readerIndex() readerIndex} 用于读操作
 * - {@link #writerIndex() writerIndex} 用于写操作
 * 下图显示了缓冲区被两个指针划分为三个区域:
 *
 * <pre>
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      |                   |     (CONTENT)    |                  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 * </pre>
 *
 * <h4>可读字节(实际内容)</h4>
 * <p>
 * 该部分存储实际数据.
 * 任何以 {@code read} or {@code skip} 名字开头的操作, 将自当前 {@link #readerIndex() readerIndex} 起获取或跳过数据,
 * 同时 {@link #readerIndex() readerIndex} 将增加读取字节数.
 * 如果读取操作的参数同样是 {@link ByteBuf}, 并且未指定目标 index, 指定 buffer 的 {@link #writerIndex() writerIndex} 将同步增加.
 * <p>
 * 如果剩余内容不足, 将抛出 {@link IndexOutOfBoundsException}.
 * 新分配的, 包装的或复制的 buffer 的 {@link #readerIndex() readerIndex} 的默认值是 {@code 0}.
 *
 * <pre>
 * // 遍历 buffer 的可读字节
 * {@link ByteBuf} buffer = ...;
 * while (buffer.isReadable()) {
 *     System.out.println(buffer.readByte());
 * }
 * </pre>
 *
 * <h4>可写字节</h4>
 * <p>
 * 该部分是需要被填充的未定义空间.
 * 任何以 {@code write} 名字开头的操作, 将自当前 {@link #writerIndex() writerIndex} 起写入数据,
 * 同时 {@link #writerIndex() writerIndex} 将增加写入字节数.
 * 如果写入操作的参数同样是 {@link ByteBuf}, 并且未指定源 index, 指定 buffer 的 {@link #readerIndex() readerIndex} 将同步增加.
 * <p>
 * 如果剩余的可写字节不足, 将抛出 {@link IndexOutOfBoundsException}.
 * 包装的或复制的 buffer 的 {@link #writerIndex() writerIndex} 的默认值是 {@link #capacity() capacity}.
 *
 * <pre>
 * // 使用随机 integer 填充 buffer 的可写字节
 * {@link ByteBuf} buffer = ...;
 * while (buffer.maxWritableBytes() >= 4) {
 *     buffer.writeInt(random.nextInt());
 * }
 * </pre>
 *
 * <h4>可丢弃的字节</h4>
 * <p>
 * 该部分包含已经被读操作读取的字节.
 * 初始时, 该部分的大小为 {@code 0}, 但随着读操作被执行, 它的大小将增大至 {@link #writerIndex() writerIndex}.
 * 通过调用 {@link #discardReadBytes()}, 已读取的字节可被丢弃, 回收未使用的区域, 如下图所示:
 *
 * <pre>
 *  BEFORE discardReadBytes()
 *
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 *
 *
 *  AFTER discardReadBytes()
 *
 *      +------------------+--------------------------------------+
 *      |  readable bytes  |    writable bytes (got more space)   |
 *      +------------------+--------------------------------------+
 *      |                  |                                      |
 * readerIndex (0) <= writerIndex (decreased)        <=        capacity
 * </pre>
 * <p>
 * 请注意, 在调用 {@link #discardReadBytes()} 后, 无法保证 writable bytes 的内容.
 * 在大多数情况下, writable bytes 将不会移动, 甚至根据底层 buffer 的实现可能会用完全不同的数据填充它.
 *
 * <h4>清除缓冲区索引</h4>
 * <p>
 * 通过调用 {@link #clear()}, 您可以同时设置 {@link #readerIndex() readerIndex} and {@link #writerIndex() writerIndex} to {@code 0}.
 * 它并不清除 buffer 的内容(e.g. 使用 {@code 0} 填充), 仅仅清除两个指针.
 * 请注意, 此操作的语义与 {@link ByteBuffer#clear()} 不同.
 *
 * <pre>
 *  BEFORE clear()
 *
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 *
 *
 *  AFTER clear()
 *
 *      +---------------------------------------------------------+
 *      |             writable bytes (got more space)             |
 *      +---------------------------------------------------------+
 *      |                                                         |
 *      0 = readerIndex = writerIndex            <=            capacity
 * </pre>
 *
 * <h3>检索操作</h3>
 * <p>
 * 对于简单的单字节的搜索, 使用 {@link #indexOf(int, int, byte)} and {@link #bytesBefore(int, int, byte)}.
 * 当你应对 {@code NUL} 终止的 string 时, {@link #bytesBefore(byte)} 特别有用.
 * 对于复杂搜索, 使用特定 {@link ByteProcessor} 实现作为入参的 {@link #forEachByte(int, int, ByteProcessor)}.
 *
 * <h3>Mark and reset</h3>
 * <p>
 * 在每个 buffer 中有两个 marker indexes, 分别用于存储 {@link #readerIndex() readerIndex} 和 {@link #writerIndex() writerIndex}.
 * 您始终可以通过调用 reset 方法来重新定位两个索引之一.
 * 除了没有 {@code readlimit} 外, 它的工作方式与 {@link InputStream} 中的 mark and reset 方法类似.
 *
 * <h3>派生(Derived) buffers</h3>
 * <p>
 * 您可以通过调用下列方法来创建已存在 buffer 的一个视图:
 * <ul>
 *   <li>{@link #duplicate()}</li>
 *   <li>{@link #slice()}</li>
 *   <li>{@link #slice(int, int)}</li>
 *   <li>{@link #readSlice(int)}</li>
 *   <li>{@link #retainedDuplicate()}</li>
 *   <li>{@link #retainedSlice()}</li>
 *   <li>{@link #retainedSlice(int, int)}</li>
 *   <li>{@link #readRetainedSlice(int)}</li>
 * </ul>
 * 派生的 buffer 将具有独立的 {@link #readerIndex() readerIndex}, {@link #writerIndex() writerIndex} and marker indexes,
 * 同时它将共享其它内部数据表示, 就像 NIO buffer 那样.
 * <p>
 * 如果需要现有 buffer 的全新副本, 请改为调用 {@link #copy()} 方法.
 *
 * <h4>Non-retained and retained derived buffers</h4>
 * <p>
 * 注意, {@link #duplicate()}, {@link #slice()}, {@link #slice(int, int)} and {@link #readSlice(int)}
 * 在返回的派生 buffer 上并不调用 {@link #retain()}, 因此它的引用计数将不会增加.
 * 如果你需要创建一个派生 buffer 同时增加引用计数, 考虑使用
 * {@link #retainedDuplicate()}, {@link #retainedSlice()}, {@link #retainedSlice(int, int)} and {@link #readRetainedSlice(int)}
 * 它们将返回一个可能产生更少垃圾的 buffer 实现.
 *
 * <h3>转换为现有的 JDK 类型/h3>
 *
 * <h4>Byte array</h4>
 * <p>
 * 如果一个 {@link ByteBuf} 由一个 byte array (i.e. {@code byte[]}) 构成, 你可以直接通过 {@link #array()} 方法访问它.
 * 想要确定一个 buffer 是否由一个 byte array 构成, 应该使用 {@link #hasArray()}.
 *
 * <h4>NIO Buffers</h4>
 * <p>
 * 如果一个 {@link ByteBuf} 可以被转换成一个共享它的内容的 NIO {@link ByteBuffer}(i.e. view buffer) 时,
 * 您可以通过 {@link #nioBuffer()} 方法得到它.
 * 想要确定一个 buffer 是否可以被转换为一个 NIO buffer, 使用 {@link #nioBufferCount()}.
 *
 * <h4>Strings</h4>
 * <p>
 * 各种 {@link #toString(Charset)} 方法将 {@link ByteBuf} 转换为 {@link String}.
 * 请注意, {@link #toString()} 不是一个转换方法.
 *
 * <h4>I/O Streams</h4>
 * <p>
 * 请参考 {@link ByteBufInputStream} and {@link ByteBufOutputStream}.
 */
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {

    /**
     * 返回此缓冲区可以包含的字节数(octets, 八位字节)
     */
    public abstract int capacity();

    /**
     * 调整缓冲区容量.
     * <ul>
     *     <li>{@code newCapacity} < 当前容量: 该缓冲区的内容被截断</li>
     *     <li>{@code newCapacity} > 当前容量: 使用未指定的数据补全, 长度为 {@code (newCapacity - currentCapacity)}</li>
     * </ul>
     *
     * @throws IllegalArgumentException {@code newCapacity} > {@link #maxCapacity()}
     */
    public abstract ByteBuf capacity(int newCapacity);

    /**
     * 返回该缓冲区允许的最大容量. 该值为 {@link #capacity()} 的上限.
     */
    public abstract int maxCapacity();

    /**
     * 返回创建该缓冲区的 {@link ByteBufAllocator}
     */
    public abstract ByteBufAllocator alloc();

    /**
     * Returns the <a href="http://en.wikipedia.org/wiki/Endianness">endianness</a> of this buffer.
     *
     * @deprecated use the Little Endian accessors, e.g. {@code getShortLE}, {@code getIntLE} instead of creating a
     * buffer with swapped {@code endianness}.
     */
    @Deprecated
    public abstract ByteOrder order();

    /**
     * Returns a buffer with the specified {@code endianness} which shares the whole region, indexes, and marks of this
     * buffer.  Modifying the content, the indexes, or the marks of the returned buffer or this buffer affects each
     * other's content, indexes, and marks.  If the specified {@code endianness} is identical to this buffer's byte
     * order, this method can return {@code this}.  This method does not modify {@code readerIndex} or {@code
     * writerIndex} of this buffer.
     *
     * @deprecated use the Little Endian accessors, e.g. {@code getShortLE}, {@code getIntLE} instead of creating a
     * buffer with swapped {@code endianness}.
     */
    @Deprecated
    public abstract ByteBuf order(ByteOrder endianness);

    /**
     * 如果该 buffer 是另一 buffer 的 wrapper, 返回底层的 buffer 实例.
     *
     * @return {@code null}: 如果该 buffer 不是一个 wrapper
     */
    public abstract ByteBuf unwrap();

    /**
     * 是否由 NIO direct buffer 构成
     */
    public abstract boolean isDirect();

    /**
     * 是否只读
     */
    public abstract boolean isReadOnly();

    /**
     * 返回该缓冲区的一个只读版本
     */
    public abstract ByteBuf asReadOnly();

    /**
     * 返回该 buffer 的 {@code readerIndex}.
     */
    public abstract int readerIndex();

    /**
     * 设置 {@code readerIndex}
     *
     * @throws IndexOutOfBoundsException 指定 {@code readerIndex} < 0 或 > {@code this.writerIndex}
     */
    public abstract ByteBuf readerIndex(int readerIndex);

    /**
     * 返回该 buffer 的 {@code writerIndex}.
     */
    public abstract int writerIndex();

    /**
     * 设置 {@code writerIndex}
     *
     * @throws IndexOutOfBoundsException 指定 {@code writerIndex} < 0 或 > {@code this.capacity}
     */
    public abstract ByteBuf writerIndex(int writerIndex);

    /**
     * 一次性设置 {@code readerIndex} and {@code writerIndex}
     * <p>
     * 当您需要担心 {@link #readerIndex(int)} and {@link #writerIndex(int)} 的调用顺序时, 该方法很有用.
     * <p>
     * 例如, 下面的代码将失败:
     *
     * <pre>
     * // 创建一个缓冲区, 它的 readerIndex, writerIndex and capacity 分别为: 0, 0, 8
     * {@link ByteBuf} buf = {@link Unpooled}.buffer(8);
     *
     * // 将抛出 IndexOutOfBoundsException, 因为指定的 readerIndex(2) 不能大于当前的 writerIndex(0)
     * buf.readerIndex(2);
     * buf.writerIndex(4);
     * </pre>
     * <p>
     * 下面的代码将失败:
     *
     * <pre>
     * // 创建一个缓冲区, 它的 readerIndex, writerIndex and capacity 分别为: 0, 0, 8
     * {@link ByteBuf} buf = {@link Unpooled}.wrappedBuffer(new byte[8]);
     *
     * // readerIndex becomes 8.
     * buf.readLong();
     *
     * // // 将抛出 IndexOutOfBoundsException, 因为指定的 writerIndex(4) 不能小于当前的 readerIndex(8)
     * buf.writerIndex(4);
     * buf.readerIndex(2);
     * </pre>
     * <p>
     * 相比之下, 此方法保证只要指定的索引满足基本约束, 就不会抛出 {@link IndexOutOfBoundsException}, 而与缓冲区的当前索引值无关: By contrast, this method
     * guarantees that it never throws an {@link IndexOutOfBoundsException} as long as the specified indexes meet basic
     * constraints, regardless what the current index values of the buffer are:
     *
     * <pre>
     * // 不论当前缓冲区的状态是什么, 下面的调用将永远成功, 只要该缓冲区的容量不少于 4
     * buf.setIndex(2, 4);
     * </pre>
     *
     * @throws IndexOutOfBoundsException <ul>
     *                                   <li>指定的 {@code readerIndex} < 0;</li>
     *                                   <li>指定的 {@code writerIndex} < 指定的 {@code writerIndex};</li>
     *                                   <li>指定的 {@code writerIndex} > {@code this.capacity}</li>
     *                                   </ul>
     */
    public abstract ByteBuf setIndex(int readerIndex, int writerIndex);

    /**
     * 可读字节数 = {@code (this.writerIndex - this.readerIndex)}
     */
    public abstract int readableBytes();

    /**
     * 可写字节数 = {@code (this.capacity - this.writerIndex)}
     */
    public abstract int writableBytes();

    /**
     * 最大可写字节数 = {@code (this.maxCapacity - this.writerIndex)}
     */
    public abstract int maxWritableBytes();

    /**
     * 返回在不涉及内部重新分配或数据复制的情况下可以写入的最大字节数.
     * {@link #writableBytes()} <= 返回值 {@link #maxWritableBytes()}
     */
    public int maxFastWritableBytes() {
        return writableBytes();
    }

    /**
     * 当且仅当 {@code (this.writerIndex - this.readerIndex)} > 0 时, 返回 {@code true}
     */
    public abstract boolean isReadable();

    /**
     * 当且仅当该 buffer 包含大于等于指定数量元素时, 返回 {@code true}
     */
    public abstract boolean isReadable(int size);

    /**
     * 当且仅当 {@code (this.capacity - this.writerIndex)} > 0 时, 返回 {@code true}
     */
    public abstract boolean isWritable();

    /**
     * 当且仅当此缓冲区具有足够的空间用来允许写入指定数量的元素时, 返回 {@code true}
     */
    public abstract boolean isWritable(int size);

    /**
     * 设定该 buffer 的 {@code readerIndex} and {@code writerIndex} 为 {@code 0}.
     * 该方法等价于 {@link #setIndex(int, int) setIndex(0, 0)}.
     * <p>
     * 请注意, 该方法不同于 NIO buffer(它将设定 {@code limit} 为该 buffer 的 {@code capacity}).
     */
    public abstract ByteBuf clear();

    /**
     * 标记此 buffer 中当前的 {@code readerIndex}.
     * 您可以通过调用 {@link #resetReaderIndex()} 将当前的 {@code readerIndex} 重新定位已标记的 {@code readerIndex}.
     * 被标记的 {@code readerIndex} 的初始值为 {@code 0}.
     */
    public abstract ByteBuf markReaderIndex();

    /**
     * 将当前的 {@code readerIndex} 重新定位已标记的 {@code readerIndex}.
     *
     * @throws IndexOutOfBoundsException 当前 {@code writerIndex} < 已标记的 {@code readerIndex}
     */
    public abstract ByteBuf resetReaderIndex();

    /**
     * 标记此 buffer 中当前的 {@code writerIndex}.
     * 您可以通过调用 {@link #resetWriterIndex()} 将当前的 {@code writerIndex} 重新定位已标记的 {@code writerIndex}.
     * 被标记的 {@code writerIndex} 的初始值为 {@code 0}.
     */
    public abstract ByteBuf markWriterIndex();

    /**
     * 将当前的 {@code writerIndex} 重新定位已标记的 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException 当前 {@code readerIndex} > 已标记的 {@code writerIndex}
     */
    public abstract ByteBuf resetWriterIndex();

    /**
     * 丢弃 0th 和 {@code readerIndex} 之间的字节.
     * 移动 {@code readerIndex} 和 {@code writerIndex} 之间的字节到 0th, 并设置 {@code readerIndex}({@code 0}) 和 {@code writerIndex}({@code oldWriterIndex - oldReaderIndex})
     * <p>
     * 请参阅类文档以获取更多详细说明.
     */
    public abstract ByteBuf discardReadBytes();

    /**
     * 类似于 {@link ByteBuf#discardReadBytes()}, 只不过该方法可能丢弃部分, 全部或者 0 个已读取字节数, 具体取决于它的内部实现.
     * 以减少整体内存宽带消耗, 而这可能会增加潜在的内存消耗.
     */
    public abstract ByteBuf discardSomeReadBytes();

    /**
     * Expands the buffer {@link #capacity()} to make sure the number of {@linkplain #writableBytes() writable bytes} is
     * equal to or greater than the specified value.  If there are enough writable bytes in this buffer, this method
     * returns with no side effect.
     *
     * @param minWritableBytes the expected minimum number of writable bytes
     * @throws IndexOutOfBoundsException if {@link #writerIndex()} + {@code minWritableBytes} &gt; {@link #maxCapacity()}.
     * @see #capacity(int)
     */
    public abstract ByteBuf ensureWritable(int minWritableBytes);

    /**
     * 扩展该 buffer 的 {@link #capacity()} 以确保 {@linkplain #writableBytes() 可写字节数} >= 指定值.
     * 不像 {@link #ensureWritable(int)}, 该方法返回一个状态值.
     *
     * @param minWritableBytes 期望的可写字节数的最小值
     * @param force            当 {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()}:
     *                         <ul>
     *                         <li>{@code true} - 当前 buffer 的 capacity 扩展为 {@link #maxCapacity()}</li>
     *                         <li>{@code false} - 当前 buffer 的 capacity 不变</li>
     *                         </ul>
     * @return {@code 0}: 当前 buffer 有足够的可写字节数, 并且它的 capacity 不变.
     * {@code 1}: 当前 buffer 没有足够的可写字节数, 并且它的 capacity 不变.
     * {@code 2}: 当前 buffer 有足够的可写字节数, 并且它的 capacity 已经增大.
     * {@code 3}: 当前 buffer 没有足够的可写字节数, 并且它的 capacity 已经增大到最大值.
     */
    public abstract int ensureWritable(int minWritableBytes, boolean force);


    /*############################################### get ###############################################*/

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 boolean.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 1} > {@code this.capacity}
     */
    public abstract boolean getBoolean(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 byte.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 1} > {@code this.capacity}
     */
    public abstract byte getByte(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 unsigned byte.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 1} > {@code this.capacity}
     */
    public abstract short getUnsignedByte(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 16-bit short integer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 2} > {@code this.capacity}
     */
    public abstract short getShort(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 16-bit short integer(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 2} > {@code this.capacity}
     */
    public abstract short getShortLE(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 unsigned 16-bit short integer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 2} > {@code this.capacity}
     */
    public abstract int getUnsignedShort(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 unsigned 16-bit short integer(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 2} > {@code this.capacity}
     */
    public abstract int getUnsignedShortLE(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 24-bit medium integer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 3} > {@code this.capacity}
     */
    public abstract int getMedium(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 24-bit medium integer(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 3} > {@code this.capacity}
     */
    public abstract int getMediumLE(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 unsigned 24-bit medium integer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 3} > {@code this.capacity}
     */
    public abstract int getUnsignedMedium(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 unsigned 24-bit medium integer(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 3} > {@code this.capacity}
     */
    public abstract int getUnsignedMediumLE(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 32-bit integer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 4} > {@code this.capacity}
     */
    public abstract int getInt(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 32-bit integer(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 4} > {@code this.capacity}
     */
    public abstract int getIntLE(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 unsigned 32-bit integer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 4} > {@code this.capacity}
     */
    public abstract long getUnsignedInt(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 unsigned 32-bit integer(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 4} > {@code this.capacity}
     */
    public abstract long getUnsignedIntLE(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 64-bit long integer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 8} > {@code this.capacity}
     */
    public abstract long getLong(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 64-bit long integer(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 8} > {@code this.capacity}
     */
    public abstract long getLongLE(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 2-byte UTF-16 character.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 2} > {@code this.capacity}
     */
    public abstract char getChar(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 32-bit floating point number.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 4} > {@code this.capacity}
     */
    public abstract float getFloat(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 32-bit floating point number(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 4} > {@code this.capacity}
     */
    public float getFloatLE(int index) {
        return Float.intBitsToFloat(getIntLE(index));
    }

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 64-bit floating point number.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 8} > {@code this.capacity}
     */
    public abstract double getDouble(int index);

    /**
     * 在此 buffer 中指定的绝对索引处获取一个 64-bit floating point number(Little Endian Byte Order).
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 8} > {@code this.capacity}
     */
    public double getDoubleLE(int index) {
        return Double.longBitsToDouble(getLongLE(index));
    }

    /**
     * 从指定的绝对索引开始, 将该 buffer 的数据转换到指定的目标 buffer, 直至目标 buffer 变为不可写.
     * 该方法大致上与 {@link #getBytes(int, ByteBuf, int, int)} 相似, 只不过它还设定目标 buffer 的 {@code writerIndex} 为
     * 原 {@code writerIndex} + 转换的字节数.
     * <p>
     * 该方法不修改 source(i.e. {@code this}) buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + dst.writableBytes} > {@code this.capacity}
     */
    public abstract ByteBuf getBytes(int index, ByteBuf dst);

    /**
     * 从指定的绝对索引开始, 将该 buffer 的数据转换到指定的目标 buffer, 直至目标 buffer 变为不可写.
     * 该方法大致上与 {@link #getBytes(int, ByteBuf, int, int)} 相似, 只不过它还设定目标 buffer 的 {@code writerIndex} 为
     * 原 {@code writerIndex} + 转换的字节数.
     * <p>
     * 该方法不修改 source(i.e. {@code this}) buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @param length the number of bytes to transfer
     * @throws IndexOutOfBoundsException {@code index} < 0 或
     *                                   {@code index + length} > {@code this.capacity} 或
     *                                   {@code length} > {@code dst.writableBytes}
     */
    public abstract ByteBuf getBytes(int index, ByteBuf dst, int length);

    /**
     * Transfers this buffer's data to the specified destination starting at the specified absolute {@code index}.
     * <p>
     * 该方法不修改 source(i.e. {@code this}) 和 destination buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @param dstIndex the first index of the destination
     * @param length   the number of bytes to transfer
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, if the specified {@code
     *                                   dstIndex} is less than {@code 0}, if {@code index + length} is greater than {@code this.capacity}, or if {@code
     *                                   dstIndex + length} is greater than {@code dst.capacity}
     */
    public abstract ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length);

    /**
     * Transfers this buffer's data to the specified destination starting at the specified absolute {@code index}.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + dst.length} > {@code this.capacity}
     */
    public abstract ByteBuf getBytes(int index, byte[] dst);

    /**
     * 自指定的绝对 {@code index} 起, 将此 buffer 的数据传输到指定目的地.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @param dstIndex 目的地的首个 index
     * @param length   传输字节数
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, if the specified {@code
     *                                   dstIndex} is less than {@code 0}, if {@code index + length} is greater than {@code this.capacity}, or if {@code
     *                                   dstIndex + length} is greater than {@code dst.length}
     */
    public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length);

    /**
     * Transfers this buffer's data to the specified destination starting at the specified absolute {@code index} until
     * the destination's position reaches its limit.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}, 但目标的 {@code position} 将会增加.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   dst.remaining()} is greater than {@code this.capacity}
     */
    public abstract ByteBuf getBytes(int index, ByteBuffer dst);

    /**
     * Transfers this buffer's data to the specified stream starting at the specified absolute {@code index}.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @param length the number of bytes to transfer
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   length} is greater than {@code this.capacity}
     * @throws IOException               if the specified stream threw an exception during I/O
     */
    public abstract ByteBuf getBytes(int index, OutputStream out, int length) throws IOException;

    /**
     * 自指定的绝对 {@code index} 开始, 将此 buffer 的数据传输到指定的 channel.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @param length 传输的最大字节数
     * @return 写入指定 channel 的实际字节数
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   length} is greater than {@code this.capacity}
     * @throws IOException               if the specified channel threw an exception during I/O
     */
    public abstract int getBytes(int index, GatheringByteChannel out, int length) throws IOException;

    /**
     * Transfers this buffer's data starting at the specified absolute {@code index} to the specified channel starting
     * at the given file position.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     * <p>
     * 该方法不修改 channel 的 position.
     *
     * @param position the file position at which the transfer is to begin
     * @param length   the maximum number of bytes to transfer
     * @return the actual number of bytes written out to the specified channel
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + length} > {@code this.capacity}
     * @throws IOException               指定的 channel 在 I/O 中抛出异常
     */
    public abstract int getBytes(int index, FileChannel out, long position, int length) throws IOException;

    /**
     * 在给定索引处, 获取给定长度的 {@link CharSequence}
     *
     * @param length  读取的长度
     * @param charset that should be used
     * @return the sequence
     * @throws IndexOutOfBoundsException {@code length} > {@code this.readableBytes}
     */
    public abstract CharSequence getCharSequence(int index, int length, Charset charset);


    /*############################################### set ###############################################*/

    /**
     * 在该 buffer 指定绝对 {@code index} 设置指定 boolean
     * Sets the specified boolean at the specified absolute {@code index} in this buffer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 1} > {@code this.capacity}
     */
    public abstract ByteBuf setBoolean(int index, boolean value);

    /**
     * Sets the specified byte at the specified absolute {@code index} in this buffer.  The 24 high-order bits of the
     * specified value are ignored.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 1} > {@code this.capacity}
     */
    public abstract ByteBuf setByte(int index, int value);

    /**
     * Sets the specified 16-bit short integer at the specified absolute {@code index} in this buffer.
     * <p>
     * 指定值的高 16 位将被忽略.(int 4 字节, short 只取低 2 字节)
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 2} > {@code this.capacity}
     */
    public abstract ByteBuf setShort(int index, int value);

    /**
     * Sets the specified 16-bit short integer at the specified absolute {@code index} in this buffer with the Little
     * Endian Byte Order.
     * <p>
     * The 16 high-order bits of the specified value are ignored.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 2} > {@code this.capacity}
     */
    public abstract ByteBuf setShortLE(int index, int value);

    /**
     * Sets the specified 24-bit medium integer at the specified absolute {@code index} in this buffer.
     * <p>
     * <p>
     * 请注意, 指定值的最高有效字节将被忽略.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 3} > {@code this.capacity}
     */
    public abstract ByteBuf setMedium(int index, int value);

    /**
     * Sets the specified 24-bit medium integer at the specified absolute {@code index} in this buffer in the Little
     * Endian Byte Order.
     * <p>
     * Please note that the most significant byte is ignored in the specified value.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 3} > {@code this.capacity}
     */
    public abstract ByteBuf setMediumLE(int index, int value);

    /**
     * Sets the specified 32-bit integer at the specified absolute {@code index} in this buffer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException {@code index} < 0 或 {@code index + 4} > {@code this.capacity}
     */
    public abstract ByteBuf setInt(int index, int value);

    /**
     * Sets the specified 32-bit integer at the specified absolute {@code index} in this buffer with Little Endian byte
     * order .
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or {@code index + 4} is
     *                                   greater than {@code this.capacity}
     */
    public abstract ByteBuf setIntLE(int index, int value);

    /**
     * Sets the specified 64-bit long integer at the specified absolute {@code index} in this buffer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or {@code index + 8} is
     *                                   greater than {@code this.capacity}
     */
    public abstract ByteBuf setLong(int index, long value);

    /**
     * Sets the specified 64-bit long integer at the specified absolute {@code index} in this buffer in Little Endian
     * Byte Order.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or {@code index + 8} is
     *                                   greater than {@code this.capacity}
     */
    public abstract ByteBuf setLongLE(int index, long value);

    /**
     * Sets the specified 2-byte UTF-16 character at the specified absolute {@code index} in this buffer.
     * <p>
     * 指定值的高 16 位将被忽略.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or {@code index + 2} is
     *                                   greater than {@code this.capacity}
     */
    public abstract ByteBuf setChar(int index, int value);

    /**
     * Sets the specified 32-bit floating-point number at the specified absolute {@code index} in this buffer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or {@code index + 4} is
     *                                   greater than {@code this.capacity}
     */
    public abstract ByteBuf setFloat(int index, float value);

    /**
     * Sets the specified 32-bit floating-point number at the specified absolute {@code index} in this buffer in Little
     * Endian Byte Order.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or {@code index + 4} is
     *                                   greater than {@code this.capacity}
     */
    public ByteBuf setFloatLE(int index, float value) {
        return setIntLE(index, Float.floatToRawIntBits(value));
    }

    /**
     * Sets the specified 64-bit floating-point number at the specified absolute {@code index} in this buffer.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or {@code index + 8} is
     *                                   greater than {@code this.capacity}
     */
    public abstract ByteBuf setDouble(int index, double value);

    /**
     * Sets the specified 64-bit floating-point number at the specified absolute {@code index} in this buffer in Little
     * Endian Byte Order.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or {@code index + 8} is
     *                                   greater than {@code this.capacity}
     */
    public ByteBuf setDoubleLE(int index, double value) {
        return setLongLE(index, Double.doubleToRawLongBits(value));
    }

    /**
     * Transfers the specified source buffer's data to this buffer starting at the specified absolute {@code index}
     * until the source buffer becomes unreadable.
     * <p>
     * This method is basically same with {@link #setBytes(int, ByteBuf,
     * int, int)}, except that this method increases the {@code readerIndex} of the source buffer by the number of the
     * transferred bytes while {@link #setBytes(int, ByteBuf, int, int)} does not.
     * <p>
     * 该方法不修改 source(i.e. {@code this}) buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   src.readableBytes} is greater than {@code this.capacity}
     */
    public abstract ByteBuf setBytes(int index, ByteBuf src);

    /**
     * Transfers the specified source buffer's data to this buffer starting at the specified absolute {@code index}.
     * This method is basically same with {@link #setBytes(int, ByteBuf, int, int)}, except that this method increases
     * the {@code readerIndex} of the source buffer by the number of the transferred bytes while {@link #setBytes(int,
     * ByteBuf, int, int)} does not. This method does not modify {@code readerIndex} or {@code writerIndex} of the
     * source buffer (i.e. {@code this}).
     *
     * @param length the number of bytes to transfer
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, if {@code index +
     *                                   length} is greater than {@code this.capacity}, or if {@code length} is greater than {@code src.readableBytes}
     */
    public abstract ByteBuf setBytes(int index, ByteBuf src, int length);

    /**
     * Transfers the specified source buffer's data to this buffer starting at the specified absolute {@code index}.
     * This method does not modify {@code readerIndex} or {@code writerIndex} of both the source (i.e. {@code this}) and
     * the destination.
     *
     * @param srcIndex the first index of the source
     * @param length   the number of bytes to transfer
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, if the specified {@code
     *                                   srcIndex} is less than {@code 0}, if {@code index + length} is greater than {@code this.capacity}, or if {@code
     *                                   srcIndex + length} is greater than {@code src.capacity}
     */
    public abstract ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length);

    /**
     * Transfers the specified source array's data to this buffer starting at the specified absolute {@code index}. This
     * method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   src.length} is greater than {@code this.capacity}
     */
    public abstract ByteBuf setBytes(int index, byte[] src);

    /**
     * Transfers the specified source array's data to this buffer starting at the specified absolute {@code index}. This
     * method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, if the specified {@code
     *                                   srcIndex} is less than {@code 0}, if {@code index + length} is greater than {@code this.capacity}, or if {@code
     *                                   srcIndex + length} is greater than {@code src.length}
     */
    public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length);

    /**
     * Transfers the specified source buffer's data to this buffer starting at the specified absolute {@code index}
     * until the source buffer's position reaches its limit. This method does not modify {@code readerIndex} or {@code
     * writerIndex} of this buffer.
     *
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   src.remaining()} is greater than {@code this.capacity}
     */
    public abstract ByteBuf setBytes(int index, ByteBuffer src);

    /**
     * Transfers the content of the specified source stream to this buffer starting at the specified absolute {@code
     * index}. This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
     *
     * @param length the number of bytes to transfer
     * @return the actual number of bytes read in from the specified channel. {@code -1} if the specified channel is
     * closed.
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   length} is greater than {@code this.capacity}
     * @throws IOException               if the specified stream threw an exception during I/O
     */
    public abstract int setBytes(int index, InputStream in, int length) throws IOException;

    /**
     * Transfers the content of the specified source channel to this buffer starting at the specified absolute {@code
     * index}. This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
     *
     * @param length the maximum number of bytes to transfer
     * @return the actual number of bytes read in from the specified channel. {@code -1} if the specified channel is
     * closed.
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   length} is greater than {@code this.capacity}
     * @throws IOException               if the specified channel threw an exception during I/O
     */
    public abstract int setBytes(int index, ScatteringByteChannel in, int length) throws IOException;

    /**
     * Transfers the content of the specified source channel starting at the given file position to this buffer starting
     * at the specified absolute {@code index}. This method does not modify {@code readerIndex} or {@code writerIndex}
     * of this buffer. This method does not modify the channel's position.
     *
     * @param position the file position at which the transfer is to begin
     * @param length   the maximum number of bytes to transfer
     * @return the actual number of bytes read in from the specified channel. {@code -1} if the specified channel is
     * closed.
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   length} is greater than {@code this.capacity}
     * @throws IOException               if the specified channel threw an exception during I/O
     */
    public abstract int setBytes(int index, FileChannel in, long position, int length) throws IOException;

    /**
     * Fills this buffer with <tt>NUL (0x00)</tt> starting at the specified absolute {@code index}. This method does not
     * modify {@code readerIndex} or {@code writerIndex} of this buffer.
     *
     * @param length the number of <tt>NUL</tt>s to write to the buffer
     * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or if {@code index +
     *                                   length} is greater than {@code this.capacity}
     */
    public abstract ByteBuf setZero(int index, int length);

    /**
     * Writes the specified {@link CharSequence} at the current {@code writerIndex} and increases the {@code
     * writerIndex} by the written bytes.
     *
     * @param index    on which the sequence should be written
     * @param sequence to write
     * @param charset  that should be used.
     * @return the written number of bytes.
     * @throws IndexOutOfBoundsException if {@code this.writableBytes} is not large enough to write the whole sequence
     */
    public abstract int setCharSequence(int index, CharSequence sequence, Charset charset);


    /*############################################### read ###############################################*/


    /**
     * Gets a boolean at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 1} in this
     * buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 1}
     */
    public abstract boolean readBoolean();

    /**
     * Gets a byte at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 1} in this
     * buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 1}
     */
    public abstract byte readByte();

    /**
     * Gets an unsigned byte at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 1} in
     * this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 1}
     */
    public abstract short readUnsignedByte();

    /**
     * Gets a 16-bit short integer at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 2}
     * in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2}
     */
    public abstract short readShort();

    /**
     * Gets a 16-bit short integer at the current {@code readerIndex} in the Little Endian Byte Order and increases the
     * {@code readerIndex} by {@code 2} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2}
     */
    public abstract short readShortLE();

    /**
     * Gets an unsigned 16-bit short integer at the current {@code readerIndex} and increases the {@code readerIndex} by
     * {@code 2} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2}
     */
    public abstract int readUnsignedShort();

    /**
     * Gets an unsigned 16-bit short integer at the current {@code readerIndex} in the Little Endian Byte Order and
     * increases the {@code readerIndex} by {@code 2} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2}
     */
    public abstract int readUnsignedShortLE();

    /**
     * Gets a 24-bit medium integer at the current {@code readerIndex} and increases the {@code readerIndex} by {@code
     * 3} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 3}
     */
    public abstract int readMedium();

    /**
     * Gets a 24-bit medium integer at the current {@code readerIndex} in the Little Endian Byte Order and increases the
     * {@code readerIndex} by {@code 3} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 3}
     */
    public abstract int readMediumLE();

    /**
     * Gets an unsigned 24-bit medium integer at the current {@code readerIndex} and increases the {@code readerIndex}
     * by {@code 3} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 3}
     */
    public abstract int readUnsignedMedium();

    /**
     * Gets an unsigned 24-bit medium integer at the current {@code readerIndex} in the Little Endian Byte Order and
     * increases the {@code readerIndex} by {@code 3} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 3}
     */
    public abstract int readUnsignedMediumLE();

    /**
     * Gets a 32-bit integer at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 4} in
     * this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4}
     */
    public abstract int readInt();

    /**
     * Gets a 32-bit integer at the current {@code readerIndex} in the Little Endian Byte Order and increases the {@code
     * readerIndex} by {@code 4} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4}
     */
    public abstract int readIntLE();

    /**
     * Gets an unsigned 32-bit integer at the current {@code readerIndex} and increases the {@code readerIndex} by
     * {@code 4} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4}
     */
    public abstract long readUnsignedInt();

    /**
     * Gets an unsigned 32-bit integer at the current {@code readerIndex} in the Little Endian Byte Order and increases
     * the {@code readerIndex} by {@code 4} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4}
     */
    public abstract long readUnsignedIntLE();

    /**
     * Gets a 64-bit integer at the current {@code readerIndex} and increases the {@code readerIndex} by {@code 8} in
     * this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8}
     */
    public abstract long readLong();

    /**
     * Gets a 64-bit integer at the current {@code readerIndex} in the Little Endian Byte Order and increases the {@code
     * readerIndex} by {@code 8} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8}
     */
    public abstract long readLongLE();

    /**
     * Gets a 2-byte UTF-16 character at the current {@code readerIndex} and increases the {@code readerIndex} by {@code
     * 2} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2}
     */
    public abstract char readChar();

    /**
     * Gets a 32-bit floating point number at the current {@code readerIndex} and increases the {@code readerIndex} by
     * {@code 4} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4}
     */
    public abstract float readFloat();

    /**
     * Gets a 32-bit floating point number at the current {@code readerIndex} in Little Endian Byte Order and increases
     * the {@code readerIndex} by {@code 4} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4}
     */
    public float readFloatLE() {
        return Float.intBitsToFloat(readIntLE());
    }

    /**
     * Gets a 64-bit floating point number at the current {@code readerIndex} and increases the {@code readerIndex} by
     * {@code 8} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8}
     */
    public abstract double readDouble();

    /**
     * Gets a 64-bit floating point number at the current {@code readerIndex} in Little Endian Byte Order and increases
     * the {@code readerIndex} by {@code 8} in this buffer.
     *
     * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8}
     */
    public double readDoubleLE() {
        return Double.longBitsToDouble(readLongLE());
    }

    /**
     * Transfers this buffer's data to a newly created buffer starting at the current {@code readerIndex} and increases
     * the {@code readerIndex} by the number of the transferred bytes (= {@code length}). The returned buffer's {@code
     * readerIndex} and {@code writerIndex} are {@code 0} and {@code length} respectively.
     *
     * @param length the number of bytes to transfer
     * @return the newly created buffer which contains the transferred bytes
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     */
    public abstract ByteBuf readBytes(int length);

    /**
     * Returns a new slice of this buffer's sub-region starting at the current {@code readerIndex} and increases the
     * {@code readerIndex} by the size of the new slice (= {@code length}).
     * <p>
     * Also be aware that this method will NOT call {@link #retain()} and so the reference count will NOT be increased.
     *
     * @param length the size of the new slice
     * @return the newly created slice
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     */
    public abstract ByteBuf readSlice(int length);

    /**
     * 返回该 buffer (自 {@code readerIndex} 起的)子区域的新的 retained 切片.
     * 设定 {@code readerIndex} = {@code readerIndex} + {@code length}.
     * <p>
     * 注意: 不像 {@link #readSlice(int)}, 该方法返回一个 {@linkplain #retain() retained} buffer.
     * 该方法的行为类似于 {@code readSlice(...).retain()}, 除了此方法可能返回产生较少垃圾的缓冲区实现.
     *
     * @param length 新分片的大小
     * @return 新创建的分片
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     */
    public abstract ByteBuf readRetainedSlice(int length);

    /**
     * Transfers this buffer's data to the specified destination starting at the current {@code readerIndex} until the
     * destination becomes non-writable, and increases the {@code readerIndex} by the number of the transferred bytes.
     * This method is basically same with {@link #readBytes(ByteBuf, int, int)}, except that this method increases the
     * {@code writerIndex} of the destination by the number of the transferred bytes while {@link #readBytes(ByteBuf,
     * int, int)} does not.
     *
     * @throws IndexOutOfBoundsException if {@code dst.writableBytes} is greater than {@code this.readableBytes}
     */
    public abstract ByteBuf readBytes(ByteBuf dst);

    /**
     * Transfers this buffer's data to the specified destination starting at the current {@code readerIndex} and
     * increases the {@code readerIndex} by the number of the transferred bytes (= {@code length}).  This method is
     * basically same with {@link #readBytes(ByteBuf, int, int)}, except that this method increases the {@code
     * writerIndex} of the destination by the number of the transferred bytes (= {@code length}) while {@link
     * #readBytes(ByteBuf, int, int)} does not.
     *
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes} or if {@code
     *                                   length} is greater than {@code dst.writableBytes}
     */
    public abstract ByteBuf readBytes(ByteBuf dst, int length);

    /**
     * Transfers this buffer's data to the specified destination starting at the current {@code readerIndex} and
     * increases the {@code readerIndex} by the number of the transferred bytes (= {@code length}).
     *
     * @param dstIndex the first index of the destination
     * @param length   the number of bytes to transfer
     * @throws IndexOutOfBoundsException if the specified {@code dstIndex} is less than {@code 0}, if {@code length} is
     *                                   greater than {@code this.readableBytes}, or if {@code dstIndex + length} is greater than {@code dst.capacity}
     */
    public abstract ByteBuf readBytes(ByteBuf dst, int dstIndex, int length);

    /**
     * Transfers this buffer's data to the specified destination starting at the current {@code readerIndex} and
     * increases the {@code readerIndex} by the number of the transferred bytes (= {@code dst.length}).
     *
     * @throws IndexOutOfBoundsException if {@code dst.length} is greater than {@code this.readableBytes}
     */
    public abstract ByteBuf readBytes(byte[] dst);

    /**
     * 自当前的 {@code readerIndex} 起, 将此 buffer 的数据传输到指定目的地, 并且 {@code readerIndex} += 已传输的字节长度({@code length}).
     *
     * @param dstIndex the first index of the destination
     * @param length   the number of bytes to transfer
     * @throws IndexOutOfBoundsException if the specified {@code dstIndex} is less than {@code 0}, if {@code length} is
     *                                   greater than {@code this.readableBytes}, or if {@code dstIndex + length} is greater than {@code dst.length}
     */
    public abstract ByteBuf readBytes(byte[] dst, int dstIndex, int length);

    /**
     * Transfers this buffer's data to the specified destination starting at the current {@code readerIndex} until the
     * destination's position reaches its limit, and increases the {@code readerIndex} by the number of the transferred
     * bytes.
     *
     * @throws IndexOutOfBoundsException if {@code dst.remaining()} is greater than {@code this.readableBytes}
     */
    public abstract ByteBuf readBytes(ByteBuffer dst);

    /**
     * Transfers this buffer's data to the specified stream starting at the current {@code readerIndex}.
     *
     * @param length the number of bytes to transfer
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     * @throws IOException               if the specified stream threw an exception during I/O
     */
    public abstract ByteBuf readBytes(OutputStream out, int length) throws IOException;

    /**
     * 将该 buffer 中自当前 {@code readerIndex} 起的数据转移至指定的 stream.
     *
     * @param length the maximum number of bytes to transfer
     * @return the actual number of bytes written out to the specified channel
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     * @throws IOException               if the specified channel threw an exception during I/O
     */
    public abstract int readBytes(GatheringByteChannel out, int length) throws IOException;

    /**
     * Gets a {@link CharSequence} with the given length at the current {@code readerIndex} and increases the {@code
     * readerIndex} by the given length.
     *
     * @param length  the length to read
     * @param charset that should be used
     * @return the sequence
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     */
    public abstract CharSequence readCharSequence(int length, Charset charset);

    /**
     * Transfers this buffer's data starting at the current {@code readerIndex} to the specified channel starting at the
     * given file position. This method does not modify the channel's position.
     *
     * @param position the file position at which the transfer is to begin
     * @param length   the maximum number of bytes to transfer
     * @return the actual number of bytes written out to the specified channel
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     * @throws IOException               if the specified channel threw an exception during I/O
     */
    public abstract int readBytes(FileChannel out, long position, int length) throws IOException;

    /**
     * {@code readerIndex} + {@code length}
     *
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     */
    public abstract ByteBuf skipBytes(int length);


    /*############################################### write ###############################################*/

    /**
     * Sets the specified boolean at the current {@code writerIndex} and increases the {@code writerIndex} by {@code 1}
     * in this buffer. If {@code this.writableBytes} is less than {@code 1}, {@link #ensureWritable(int)} will be called
     * in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeBoolean(boolean value);

    /**
     * Sets the specified byte at the current {@code writerIndex} and increases the {@code writerIndex} by {@code 1} in
     * this buffer. The 24 high-order bits of the specified value are ignored. If {@code this.writableBytes} is less
     * than {@code 1}, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeByte(int value);

    /**
     * Sets the specified 16-bit short integer at the current {@code writerIndex} and increases the {@code writerIndex}
     * by {@code 2} in this buffer.  The 16 high-order bits of the specified value are ignored. If {@code
     * this.writableBytes} is less than {@code 2}, {@link #ensureWritable(int)} will be called in an attempt to expand
     * capacity to accommodate.
     */
    public abstract ByteBuf writeShort(int value);

    /**
     * Sets the specified 16-bit short integer in the Little Endian Byte Order at the current {@code writerIndex} and
     * increases the {@code writerIndex} by {@code 2} in this buffer. The 16 high-order bits of the specified value are
     * ignored. If {@code this.writableBytes} is less than {@code 2}, {@link #ensureWritable(int)} will be called in an
     * attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeShortLE(int value);

    /**
     * Sets the specified 24-bit medium integer at the current {@code writerIndex} and increases the {@code writerIndex}
     * by {@code 3} in this buffer. If {@code this.writableBytes} is less than {@code 3}, {@link #ensureWritable(int)}
     * will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeMedium(int value);

    /**
     * Sets the specified 24-bit medium integer at the current {@code writerIndex} in the Little Endian Byte Order and
     * increases the {@code writerIndex} by {@code 3} in this buffer. If {@code this.writableBytes} is less than {@code
     * 3}, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeMediumLE(int value);

    /**
     * Sets the specified 32-bit integer at the current {@code writerIndex} and increases the {@code writerIndex} by
     * {@code 4} in this buffer. If {@code this.writableBytes} is less than {@code 4}, {@link #ensureWritable(int)} will
     * be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeInt(int value);

    /**
     * Sets the specified 32-bit integer at the current {@code writerIndex} in the Little Endian Byte Order and
     * increases the {@code writerIndex} by {@code 4} in this buffer. If {@code this.writableBytes} is less than {@code
     * 4}, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeIntLE(int value);

    /**
     * Sets the specified 64-bit long integer at the current {@code writerIndex} and increases the {@code writerIndex}
     * by {@code 8} in this buffer. If {@code this.writableBytes} is less than {@code 8}, {@link #ensureWritable(int)}
     * will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeLong(long value);

    /**
     * Sets the specified 64-bit long integer at the current {@code writerIndex} in the Little Endian Byte Order and
     * increases the {@code writerIndex} by {@code 8} in this buffer. If {@code this.writableBytes} is less than {@code
     * 8}, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeLongLE(long value);

    /**
     * Sets the specified 2-byte UTF-16 character at the current {@code writerIndex} and increases the {@code
     * writerIndex} by {@code 2} in this buffer.  The 16 high-order bits of the specified value are ignored. If {@code
     * this.writableBytes} is less than {@code 2}, {@link #ensureWritable(int)} will be called in an attempt to expand
     * capacity to accommodate.
     */
    public abstract ByteBuf writeChar(int value);

    /**
     * Sets the specified 32-bit floating point number at the current {@code writerIndex} and increases the {@code
     * writerIndex} by {@code 4} in this buffer. If {@code this.writableBytes} is less than {@code 4}, {@link
     * #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeFloat(float value);

    /**
     * Sets the specified 32-bit floating point number at the current {@code writerIndex} in Little Endian Byte Order
     * and increases the {@code writerIndex} by {@code 4} in this buffer. If {@code this.writableBytes} is less than
     * {@code 4}, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public ByteBuf writeFloatLE(float value) {
        return writeIntLE(Float.floatToRawIntBits(value));
    }

    /**
     * Sets the specified 64-bit floating point number at the current {@code writerIndex} and increases the {@code
     * writerIndex} by {@code 8} in this buffer. If {@code this.writableBytes} is less than {@code 8}, {@link
     * #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeDouble(double value);

    /**
     * Sets the specified 64-bit floating point number at the current {@code writerIndex} in Little Endian Byte Order
     * and increases the {@code writerIndex} by {@code 8} in this buffer. If {@code this.writableBytes} is less than
     * {@code 8}, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public ByteBuf writeDoubleLE(double value) {
        return writeLongLE(Double.doubleToRawLongBits(value));
    }

    /**
     * Transfers the specified source buffer's data to this buffer starting at the current {@code writerIndex} until the
     * source buffer becomes unreadable, and increases the {@code writerIndex} by the number of the transferred bytes.
     * This method is basically same with {@link #writeBytes(ByteBuf, int, int)}, except that this method increases the
     * {@code readerIndex} of the source buffer by the number of the transferred bytes while {@link #writeBytes(ByteBuf,
     * int, int)} does not. If {@code this.writableBytes} is less than {@code src.readableBytes}, {@link
     * #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeBytes(ByteBuf src);

    /**
     * Transfers the specified source buffer's data to this buffer starting at the current {@code writerIndex} and
     * increases the {@code writerIndex} by the number of the transferred bytes (= {@code length}).  This method is
     * basically same with {@link #writeBytes(ByteBuf, int, int)}, except that this method increases the {@code
     * readerIndex} of the source buffer by the number of the transferred bytes (= {@code length}) while {@link
     * #writeBytes(ByteBuf, int, int)} does not. If {@code this.writableBytes} is less than {@code length}, {@link
     * #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     *
     * @param length the number of bytes to transfer
     * @throws IndexOutOfBoundsException if {@code length} is greater then {@code src.readableBytes}
     */
    public abstract ByteBuf writeBytes(ByteBuf src, int length);

    /**
     * Transfers the specified source buffer's data to this buffer starting at the current {@code writerIndex} and
     * increases the {@code writerIndex} by the number of the transferred bytes (= {@code length}). If {@code
     * this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)} will be called in an attempt to
     * expand capacity to accommodate.
     *
     * @param srcIndex the first index of the source
     * @param length   the number of bytes to transfer
     * @throws IndexOutOfBoundsException if the specified {@code srcIndex} is less than {@code 0}, or if {@code srcIndex
     *                                   + length} is greater than {@code src.capacity}
     */
    public abstract ByteBuf writeBytes(ByteBuf src, int srcIndex, int length);

    /**
     * Transfers the specified source array's data to this buffer starting at the current {@code writerIndex} and
     * increases the {@code writerIndex} by the number of the transferred bytes (= {@code src.length}). If {@code
     * this.writableBytes} is less than {@code src.length}, {@link #ensureWritable(int)} will be called in an attempt to
     * expand capacity to accommodate.
     */
    public abstract ByteBuf writeBytes(byte[] src);

    /**
     * Transfers the specified source array's data to this buffer starting at the current {@code writerIndex} and
     * increases the {@code writerIndex} by the number of the transferred bytes (= {@code length}). If {@code
     * this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)} will be called in an attempt to
     * expand capacity to accommodate.
     *
     * @param srcIndex the first index of the source
     * @param length   the number of bytes to transfer
     * @throws IndexOutOfBoundsException if the specified {@code srcIndex} is less than {@code 0}, or if {@code srcIndex
     *                                   + length} is greater than {@code src.length}
     */
    public abstract ByteBuf writeBytes(byte[] src, int srcIndex, int length);

    /**
     * Transfers the specified source buffer's data to this buffer starting at the current {@code writerIndex} until the
     * source buffer's position reaches its limit, and increases the {@code writerIndex} by the number of the
     * transferred bytes. If {@code this.writableBytes} is less than {@code src.remaining()}, {@link
     * #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     */
    public abstract ByteBuf writeBytes(ByteBuffer src);

    /**
     * Transfers the content of the specified stream to this buffer starting at the current {@code writerIndex} and
     * increases the {@code writerIndex} by the number of the transferred bytes. If {@code this.writableBytes} is less
     * than {@code length}, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to
     * accommodate.
     *
     * @param length the number of bytes to transfer
     * @return the actual number of bytes read in from the specified stream
     * @throws IOException if the specified stream threw an exception during I/O
     */
    public abstract int writeBytes(InputStream in, int length) throws IOException;

    /**
     * Transfers the content of the specified channel to this buffer starting at the current {@code writerIndex} and
     * increases the {@code writerIndex} by the number of the transferred bytes. If {@code this.writableBytes} is less
     * than {@code length}, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to
     * accommodate.
     *
     * @param length the maximum number of bytes to transfer
     * @return the actual number of bytes read in from the specified channel
     * @throws IOException if the specified channel threw an exception during I/O
     */
    public abstract int writeBytes(ScatteringByteChannel in, int length) throws IOException;

    /**
     * Transfers the content of the specified channel starting at the given file position to this buffer starting at the
     * current {@code writerIndex} and increases the {@code writerIndex} by the number of the transferred bytes. This
     * method does not modify the channel's position. If {@code this.writableBytes} is less than {@code length}, {@link
     * #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     *
     * @param position the file position at which the transfer is to begin
     * @param length   the maximum number of bytes to transfer
     * @return the actual number of bytes read in from the specified channel
     * @throws IOException if the specified channel threw an exception during I/O
     */
    public abstract int writeBytes(FileChannel in, long position, int length) throws IOException;

    /**
     * Fills this buffer with <tt>NUL (0x00)</tt> starting at the current {@code writerIndex} and increases the {@code
     * writerIndex} by the specified {@code length}. If {@code this.writableBytes} is less than {@code length}, {@link
     * #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     *
     * @param length the number of <tt>NUL</tt>s to write to the buffer
     */
    public abstract ByteBuf writeZero(int length);

    /**
     * Writes the specified {@link CharSequence} at the current {@code writerIndex} and increases the {@code
     * writerIndex} by the written bytes. in this buffer. If {@code this.writableBytes} is not large enough to write the
     * whole sequence, {@link #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
     *
     * @param sequence to write
     * @param charset  that should be used
     * @return the written number of bytes
     */
    public abstract int writeCharSequence(CharSequence sequence, Charset charset);

    /**
     * 定位在此缓冲区中指定的 {@code value} 的第一个匹配项.
     * <p>
     * 需要注意, 入参不同, 检索行为不同:
     * - fromIndex <= toIndex: firstIndexOf, fromIndex <= index < toIndex
     * - fromIndex > toIndex: lastIndexOf(reversed order), fromIndex > index >= toIndex
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} or {@code writerIndex}
     *
     * @return 第一次出现的绝对索引, {@code -1} otherwise
     */
    public abstract int indexOf(int fromIndex, int toIndex, byte value);

    /**
     * 定位在此缓冲区中指定的 {@code value} 的第一个匹配项.
     * <p>
     * 检索范围: {@code readerIndex} <= index < {@code writerIndex}
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} or {@code writerIndex}
     *
     * @return {@code readerIndex} 和第一个匹配项间的字节数.  {@code -1}: otherwise.
     */
    public abstract int bytesBefore(byte value);

    /**
     * Locates the first occurrence of the specified {@code value} in this buffer.  The search starts from the current
     * {@code readerIndex} (inclusive) and lasts for the specified {@code length}.
     * <p>
     * This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
     *
     * @return the number of bytes between the current {@code readerIndex} and the first occurrence if found. {@code -1}
     * otherwise.
     * @throws IndexOutOfBoundsException if {@code length} is greater than {@code this.readableBytes}
     */
    public abstract int bytesBefore(int length, byte value);

    /**
     * Locates the first occurrence of the specified {@code value} in this buffer.
     * <p>
     * 检索范围: {@code index} <= index < {@code index + length}
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} or {@code writerIndex}
     *
     * @return {@code index} 和第一个匹配项间的字节数.  {@code -1}: otherwise.
     * @throws IndexOutOfBoundsException {@code index + length} > {@code this.capacity}
     */
    public abstract int bytesBefore(int index, int length, byte value);

    /**
     * 使用指定的 {@code Processor} 以 ascending order 遍历此缓冲区的可读字节.
     *
     * @return {@code -1}: 如果处理器迭代到或超出可读字节的末尾
     * The last-visited index: 如果 {@link ByteProcessor#process(byte)} 返回 {@code false}.
     */
    public abstract int forEachByte(ByteProcessor processor);

    /**
     * Iterates over the specified area of this buffer with the specified {@code processor} in ascending order.
     * 范围: {@code index} <= i <= {@code (index + length - 1)}
     *
     * @return {@code -1} if the processor iterated to or beyond the end of the specified area. The last-visited index
     * If the {@link ByteProcessor#process(byte)} returned {@code false}.
     */
    public abstract int forEachByte(int index, int length, ByteProcessor processor);

    /**
     * Iterates over the readable bytes of this buffer with the specified {@code processor} in descending order.
     *
     * @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes. The last-visited
     * index If the {@link ByteProcessor#process(byte)} returned {@code false}.
     */
    public abstract int forEachByteDesc(ByteProcessor processor);

    /**
     * Iterates over the specified area of this buffer with the specified {@code processor} in descending order. (i.e.
     * {@code (index + length - 1)}, {@code (index + length - 2)}, ... {@code index})
     *
     * @return {@code -1} if the processor iterated to or beyond the beginning of the specified area. The last-visited
     * index If the {@link ByteProcessor#process(byte)} returned {@code false}.
     */
    public abstract int forEachByteDesc(int index, int length, ByteProcessor processor);

    /**
     * 返回该 buffer 的可读字节的副本.
     * 返回 buffer 和 this buffer 的内容不相互影响.
     * 该方法等价于 {@code buf.copy(buf.readerIndex(), buf.readableBytes())}.
     * 该方法不修改 this buffer 的 {@code readerIndex} or {@code writerIndex}.
     */
    public abstract ByteBuf copy();

    /**
     * Returns a copy of this buffer's sub-region.  Modifying the content of the returned buffer or this buffer does not
     * affect each other at all. This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
     */
    public abstract ByteBuf copy(int index, int length);

    /**
     * 返回该 buffer 可读字节的一个切片.
     * 返回 buffer 和 this buffer 的内容相互影响, 同时它们维护相互独立的 indexes and marks.
     * 该方法等价于 {@code buf.slice(buf.readerIndex(), buf.readableBytes())}.
     * 该方法不修改 this buffer 的 {@code readerIndex} or {@code writerIndex}.
     * <p>
     * 注意, 该方法并不会调用 {@link #retain()}, 所以引用计数将不会增加.
     */
    public abstract ByteBuf slice();

    /**
     * 返回该 buffer 可读字节的一个 retained 切片.
     * 返回 buffer 和 this buffer 的内容相互影响, 同时它们维护相互独立的 indexes and marks.
     * 该方法等价于 {@code buf.slice(buf.readerIndex(), buf.readableBytes())}.
     * 该方法不修改 this buffer 的 {@code readerIndex} or {@code writerIndex}.
     * <p>
     * 注意: 不像 {@link #slice()}, 该方法返回一个 {@linkplain #retain() retained} buffer.
     * 该方法的行为类似于 {@code slice().retain()}, 不同之处在于此方法可能返回一个产生较少垃圾的缓冲区实现.
     */
    public abstract ByteBuf retainedSlice();

    /**
     * 返回该 buffer 子区域的一部分.
     * 返回 buffer 和 this buffer 的内容相互影响, 同时它们维护相互独立的 indexes and marks.
     * 该方法不修改 this buffer 的 {@code readerIndex} or {@code writerIndex}.
     * <p>
     * 注意: 该方法未调用 {@link #retain()}, 因此引用计数将不增加.
     */
    public abstract ByteBuf slice(int index, int length);

    /**
     * Returns a retained slice of this buffer's sub-region. Modifying the content of the returned buffer or this buffer
     * affects each other's content while they maintain separate indexes and marks. This method does not modify {@code
     * readerIndex} or {@code writerIndex} of this buffer.
     * <p>
     * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}. This
     * method behaves similarly to {@code slice(...).retain()} except that this method may return a buffer
     * implementation that produces less garbage.
     */
    public abstract ByteBuf retainedSlice(int index, int length);

    /**
     * 返回一个共享该 buffer 整个区域的 buffer.
     * <p>
     * 返回 buffer 和 this buffer 的内容相互影响, 同时它们维护相互独立的 indexes and marks.
     * <p>
     * 该方法不修改 this buffer 的 {@code readerIndex} or {@code writerIndex}.
     * <p>
     * reader and writer marks 将不会重复.
     * <p>
     * 同样需要注意的是, 该方法将不调用 {@link #retain()}, 因此引用计数将不增加.
     *
     * @return 一个 buffer， 它的可读内容等价于 {@link #slice()} 返回的 buffer.
     * 但是, 该 buffer 将共享底层 buffer 的容量, 因此
     * A buffer whose readable content is equivalent to the buffer returned by {@link #slice()}. However this
     * buffer will share the capacity of the underlying buffer, and therefore allows access to all of the underlying
     * content if necessary.
     */
    public abstract ByteBuf duplicate();

    /**
     * 返回共享该 buffer 所有区域的一个 retained buffer.
     * 返回 buffer 和 this buffer 的内容相互影响, 同时它们维护相互独立的 indexes and marks.
     * 该方法等价于 {@code buf.slice(0, buf.capacity())}.
     * 该方法不修改 this buffer 的 {@code readerIndex} or {@code writerIndex}.
     * <p>
     * 注意: 不像 {@link #slice(int, int)}, 该方法返回一个 {@linkplain #retain() retained} buffer.
     * 该方法的行为类似于 {@code duplicate().retain()}, 不同之处在于此方法可能返回一个产生较少垃圾的缓冲区实现.
     */
    public abstract ByteBuf retainedDuplicate();

    /**
     * 返回组成此 buffer 的 NIO {@link ByteBuffer} 的最大数量.
     * <p>
     * 注意, {@link #nioBuffers()} 或 {@link #nioBuffers(int, int)} 可能返回较少数量的 {@link ByteBuffer}
     *
     * @return {@code -1}: 此 buffer 底层没有 {@link ByteBuffer}
     * {@link ByteBuffer} 数量: 此 buffer 底层至少有一个 {@link ByteBuffer}
     * 注意, 为了避免混淆, 此方法不返回 {@code 0}
     * @see #nioBuffer()
     * @see #nioBuffer(int, int)
     * @see #nioBuffers()
     * @see #nioBuffers(int, int)
     */
    public abstract int nioBufferCount();

    /**
     * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}. The returned buffer either share or contains
     * the copied content of this buffer, while changing the position and limit of the returned NIO buffer does not
     * affect the indexes and marks of this buffer. This method is identical to {@code buf.nioBuffer(buf.readerIndex(),
     * buf.readableBytes())}. This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
     * Please note that the returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic
     * buffer and it adjusted its capacity.
     *
     * @throws UnsupportedOperationException if this buffer cannot create a {@link ByteBuffer} that shares the content
     *                                       with itself
     * @see #nioBufferCount()
     * @see #nioBuffers()
     * @see #nioBuffers(int, int)
     */
    public abstract ByteBuffer nioBuffer();

    /**
     * 将此 buffer 的子区域暴露为一个 NIO {@link ByteBuffer}.
     * 返回的 buffer 共享或包含此 buffer 被复制的内容, 同时改变返回的 NIO buffer 的 position 和 limit 并不会影响该 buffer 的 indexes 和 marks.
     * 该方法并不会修改此 buffer 的 {@code readerIndex} or {@code writerIndex}.
     * 请注意, 如果该 buffer 是动态 buffer, 同时该 buffer 已调整它的 capacity, 返回的 NIO buffer 将不能看见此 buffer 的变更.
     *
     * @throws UnsupportedOperationException 如果此 buffer 不能创建一个共享它自身内容的 {@link ByteBuffer}
     * @see #nioBufferCount()
     * @see #nioBuffers()
     * @see #nioBuffers(int, int)
     */
    public abstract ByteBuffer nioBuffer(int index, int length);

    /**
     * 仅供内部使用: 暴露内部 NIO buffer
     */
    public abstract ByteBuffer internalNioBuffer(int index, int length);

    /**
     * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}'s. The returned buffer either share or contains
     * the copied content of this buffer, while changing the position and limit of the returned NIO buffer does not
     * affect the indexes and marks of this buffer. This method does not modify {@code readerIndex} or {@code
     * writerIndex} of this buffer. Please note that the returned NIO buffer will not see the changes of this buffer if
     * this buffer is a dynamic buffer and it adjusted its capacity.
     *
     * @throws UnsupportedOperationException if this buffer cannot create a {@link ByteBuffer} that shares the content
     *                                       with itself
     * @see #nioBufferCount()
     * @see #nioBuffer()
     * @see #nioBuffer(int, int)
     */
    public abstract ByteBuffer[] nioBuffers();

    /**
     * 将此 buffer 的指定 index 和长度处的字节暴露为 NIO {@link ByteBuffer}'s.
     * <p>
     * 返回的 buffer 共享或者包含该 buffer 被复制的内容, 变更返回 NIO buffer 的 position 和 limit 并不会影响该 buffer 的 index 和 mark.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     * <p>
     * 请注意, 如果该 buffer 是动态 buffer, 同时该 buffer 已调整它的 capacity, 返回的 NIO buffer 将不能看见此 buffer 的变更.
     *
     * @throws UnsupportedOperationException 如果该 buffer 不能创建与其自身共享内存的 {@link ByteBuffer}
     * @see #nioBufferCount()
     * @see #nioBuffer()
     * @see #nioBuffer(int, int)
     */
    public abstract ByteBuffer[] nioBuffers(int index, int length);

    /**
     * 当且仅当该 buffer 有底层 byte array 时, 返回 {@code true}.
     * <p>
     * 如果该方法返回 {@code true}, 您可以安全的调用 {@link #array()} and {@link #arrayOffset()}.
     */
    public abstract boolean hasArray();

    /**
     * 返回该 buffer 的底层 byte array
     *
     * @throws UnsupportedOperationException 没有可访问的 backing byte array
     */
    public abstract byte[] array();

    /**
     * 返回此 buffer 底层 array 的第一个字节的偏移量.
     *
     * @throws UnsupportedOperationException 没有可访问的底层字节数组
     */
    public abstract int arrayOffset();

    /**
     * 当且仅当此 buffer 拥有对指向 backing 数据的低级内存地址的引用时, 才返回 {@code true}.
     */
    public abstract boolean hasMemoryAddress();

    /**
     * 返回指向 backing 数据的首字节的低级内存地址
     *
     * @throws UnsupportedOperationException if this buffer does not support accessing the low-level memory address
     */
    public abstract long memoryAddress();

    /**
     * 如果该 {@link ByteBuf} 实现由单个内存区域构成, 返回 {@code true}.
     * <p>
     * Composite buffer 实现必须返回 {@code false}, 即使它们当前持有 <= 1 个 components.
     * 对于返回 {@code true} 的 buffer, 可以确保对 {@link #discardReadBytes()} 的成功调用将使得
     * {@link #maxFastWritableBytes()} += 当前 {@code readerIndex}.
     * <p>
     * 该方法默认返回 {@code false}. {@code false} 返回值并不一定意味着实现是 composite 或者它不由单个内存区域构成.
     */
    public boolean isContiguous() {
        return false;
    }

    /**
     * Decodes this buffer's readable bytes into a string with the specified character set name.
     * <p>
     * 该方法等价于 {@code buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName)}.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     *
     * @throws UnsupportedCharsetException if the specified character set name is not supported by the current VM
     */
    public abstract String toString(Charset charset);

    /**
     * Decodes this buffer's sub-region into a string with the specified character set.
     * <p>
     * 该方法不修改该 buffer 的 {@code readerIndex} 或 {@code writerIndex}.
     */
    public abstract String toString(int index, int length, Charset charset);

    /**
     * 返回根据 buffer 的内容计算出的 hash 值.
     * <p>
     * 如果有一个 byte array {@linkplain #equals(Object) equal to} this array, 两个 array 均返回相同的值.
     */
    @Override
    public abstract int hashCode();

    /**
     * 确定指定 buffer 的内容是否等价于 this.
     * <p>
     * 这里'等价'意味着:
     * <ul>
     * <li>两个 buffer 内容的 size 相等</li>
     * <li>两个 buffer 内容的每个字节均一样.</li>
     * </ul>
     * 请注意: 它并不比较 {@link #readerIndex()} 或 {@link #writerIndex()}.
     * 对于 {@code null} 或者非 {@link ByteBuf} 类型, 方法返回 {@code false}.
     */
    @Override
    public abstract boolean equals(Object obj);

    /**
     * 比较 buffer 的内容.
     * <p>
     * 比较方式等同于多种语言的字符比较函数, 如 {@code strcmp}, {@code memcmp} 和 {@link String#compareTo(String)}.
     */
    @Override
    public abstract int compareTo(ByteBuf buffer);

    /**
     * 返回该 buffer 的字符串表示.
     * <p>
     * 该方法并不一定需要返回该 buffer 的全部内容, 而是返回关键属性的值, 如 {@link #readerIndex()}, {@link #writerIndex()}
     * 和 {@link #capacity()}.
     */
    @Override
    public abstract String toString();

    @Override
    public abstract ByteBuf retain(int increment);

    @Override
    public abstract ByteBuf retain();

    @Override
    public abstract ByteBuf touch();

    @Override
    public abstract ByteBuf touch(Object hint);

    /**
     * 在 {@link AbstractByteBuf#ensureAccessible()} 内部使用, 用于尝试防止该 buffer 被释放后被继续使用(best-effort).
     */
    boolean isAccessible() {
        return refCnt() != 0;
    }
}
